<?php
/**
 * @Name: BaseLogic.php
 * @Author: yashuai<1762910894@qq.com>
 */

namespace app\common\logic;

use think\Model;
use HugCode\PhpUnits\InstanceTool;

abstract class BaseLogic
{

    use InstanceTool;

    abstract protected function setModel(): string;

    private $config_database = [];

    /**
     * @Desc 获取模型
     * @author yashuai<1762910894@qq.com>
     */
    protected function getModel(): Model
    {
        return app()->make($this->setModel());
    }


    /**
     * @Desc 获取主键
     * @return array|string
     * @author yashuai<1762910894@qq.com>
     */
    public function getPk()
    {
        return $this->getModel()->getPk();
    }

    /**
     * @Desc 获取query
     * @param array|integer|bool $id
     * @return Model
     * @author yashuai<1762910894@qq.com>
     */
    public function query($id = false)
    {
        if (empty($id)) {
            return $this->getModel();
        } else {
            $where = is_array($id) ? $id : [$this->getPk() => $id];
            return $this->getModel()->where($where);
        }
    }

    /**
     * @Desc 获取总数
     * @param array $where
     * @return int
     * @throws \think\db\exception\DbException
     * @author yashuai<1762910894@qq.com>
     */
    public function count(array $where = [])
    {
        return $this->getModel()->where($where)->count();
    }

    /**
     * @Desc 字段值聚合
     * @param string $field
     * @param array $where
     * @return float
     * @author yashuai<1762910894@qq.com>
     */
    public function sum(string $field, array $where = [])
    {
        return $this->getModel()->where($where)->sum($field);
    }

    /**
     * @Desc 查询某一列的值
     * @param $id
     * @param string|array $field
     * @param string $key
     * @return array
     * @author yashuai<1762910894@qq.com>
     */
    public function column($id, $field, string $key = '')
    {
        $where = $this->idWhere($id);
        return $this->getModel()->where($where)->column($field, $key);
    }

    /**
     * @Desc 获取单条数据
     * @param $id
     * @param array $field
     * @param array $with
     * @param array $setting
     * @return array
     * @author yashuai<1762910894@qq.com>
     */
    public function get($id, array $field = [], array $with = [], array $setting = [])
    {
        try {
            $where  = $this->idWhere($id);
            $result = $this->getModel()->where($where)->when(count($with), function ($query) use ($with) {
                $query->with($with);
            })->when(_array_field($setting, 'lock'), function ($query) {
                $query->lock(true);
            })->field($field ?? ['*'])->findOrEmpty();
            return $result->isEmpty() ? [] : $result->toArray();
        } catch (\Exception $e) {
            _throw('查询失败:' . $e->getMessage(), 105002);
        }
        return [];
    }

    /**
     * @Desc 获取value
     * @param $id
     * @param string $field
     * @return mixed
     * @author yashuai<1762910894@qq.com>
     */
    public function value($id, string $field)
    {
        $where = $this->idWhere($id);
        return $this->getModel()->where($where)->value($field);
    }

    /**
     * @Desc 列表
     * @param array $where
     * @param string|array $field
     * @param int $page
     * @param int $limit
     * @param array $with
     * @param array $order
     * @param array $setting
     * @return array|void
     * @author yashuai<1762910894@qq.com>
     */
    public function selectList(array $where, $field = '*', int $page = 0, int $limit = 0, array $with = [], array $order = [], array $setting = [])
    {
        try {
            return $this->getModel()->where($where)->field($field)
                ->when($page && $limit, function ($query) use ($page, $limit) {
                    $query->page($page, $limit);
                })->when(count($order), function ($query) use ($order) {
                    $query->order($order);
                })->when(count($with), function ($query) use ($with) {
                    $query->with($with);
                })->when(_array_field($setting, 'lock'), function ($query) {
                    $query->lock(true);
                })->select();
        } catch (\Exception $e) {
            _throw('数据查询失败：' . $e->getMessage(), 105002);
        }
    }


    /**
     * @Desc 更新记录
     * @param array|int $id
     * @param array $data
     * @return false|Model
     * @author yashuai<1762910894@qq.com>
     */
    public function update($id, array $data)
    {
        $where = $this->idWhere($id);
        try {
            $data = $this->timestamp($data, 'update');
            return $this->getModel()->where($where)->update($data);
        } catch (\Exception $e) {
            _throw($e->getMessage(), 105002);
        }
        return false;
    }

    /**
     * @Desc 验证记录是否存在，不存在抛出异常
     * @param $id
     * @param array $field
     * @return array
     * @return array
     * @author yashuai<1762910894@qq.com>
     */
    public function validatorRow($id, array $field = [])
    {
        $where  = $this->idWhere($id);
        $field  = empty($field) ? [$this->getPk()] : $field;
        $result = $this->getModel()->where($where)->field($field)->findOrEmpty();
        if ($result->isEmpty()) {
            _throw('当前记录不存在', 106001);
        }
        return $result->toArray();
    }

    /**
     * @Desc 物理删除
     * @param array|int $where
     * @return bool
     * @author yashuai<1762910894@qq.com>
     */
    public function physicalDeleteRow($where = [])
    {
        $where = $this->idWhere($where);
        if (empty($where)) {
            return false;
        }
        return $this->getModel()->where($where)->delete();
    }

    /**
     * @Desc id转为条件
     * @param array|int $id
     * @return array
     * @author yashuai<1762910894@qq.com>
     */
    public function idWhere($id)
    {
        if (empty($id)) {
            return [];
        }
        return is_array($id) ? $id : [$this->getPk() => $id];
    }

    /**
     * @Desc 时间戳处理
     * @param array $data
     * @param string $type
     * @return array
     * @author yashuai<1762910894@qq.com>
     */
    public function timestamp(array $data = [], string $type = 'create')
    {
        if (empty($this->config_database)) {
            $config                = config('database');
            $datetime_field        = explode(',', $config['datetime_field'] ?? '');
            $this->config_database = [
                'auto_timestamp'    => $config['auto_timestamp'],
                'create_time_field' => $datetime_field[0] ?? '',
                'update_time_field' => $datetime_field[1] ?? ''
            ];
        }
        if ($type == 'update') {
            $data[$this->config_database['update_time_field']] = time();
        } elseif ($type == 'create') {
            $field = $this->config_database['create_time_field'];
            if (is_array(reset($data))) {
                foreach ($data as &$item) {
                    $item[$field] = time();
                }
            } else {
                $data[$field] = time();
            }
        }
        return $data;
    }

}
